Next | Prev | Up | Top | Contents | Index
Long-Term Locks
Sometimes you need a lock that can be held for a longer period, over a call to a function that can sleep. IRIX provides three types of such locks: mutex locks, sleep locks, and reader-writer locks.
Using Mutex Locks
Mutex locks are designed for mutual exclusion (as the name suggests). The IRIX implementation of mutex locks is compatible with the kmutex_t lock type of SunOS(TM), but optimized for use in Silicon Graphics hardware systems. The mutex functions are summarized in Table 9-17.
Functions for Mutex Locks
Function Name | Header Files | Can Sleep? | Purpose |
---|
MUTEX_ALLOC(D3) | types.h & kmem.h & ksynch.h | Y | Allocate and initialize a mutex lock. |
MUTEX_INIT(D3) | types.h & ksynch.h | N | Initialize an existing mutex lock. |
MUTEX_DESTROY(D3) | types.h & ksynch.h | N | Deinitialize a mutex lock. |
MUTEX_DEALLOC(D3) | types.h & ksynch.h | N | Deinitialize and free a dynamically allocated mutex lock. |
MUTEX_LOCK(D3) | types.h & kmem.h & ksynch.h | Y | Claim a mutex lock. |
MUTEX_TRYLOCK(D3) | types.h & ksynch.h | N | Conditionally claim a mutex lock. |
MUTEX_UNLOCK(D3) | types.h & ksynch.h | N | Release a mutex lock. |
MUTEX_WAITQ(D3) | types.h & ksynch.h | N | Get the number of processes blocked by mutex lock. |
MUTEX_ISLOCKED(D3) | types.h & ksynch.h | N | Test if a mutex lock is owned. |
MUTEX_MINE(D3) | types.h & ksynch.h | N | Test if a mutex lock is owned by this process. |
Although allocation and deallocation functions are supplied, a mutex_t type is a small object that is normally allocated as a static variable or as a field of a structure. The MUTEX_INIT() operation prepares a statically-allocated mutex_t for use.
Once initialized, a mutex lock is used to gain exclusive use of the resource with which you have associated it. The mutex lock has the following important advantages over a basic lock:
- The mutex lock can safely be held over a call to a function that sleeps.
- The mutex lock supports the inquiry functions MUTEX_WAITQ, MUTEX_ISLOCKED, and MUTEX_MINE.
- When a debugging kernel is used (see "Including Lock Metering in the Kernel Image") a mutex lock can be instrumented to keep statistics of its use.
The mutex lock implementation provides priority inheritance. When a low-priority process owns a mutex lock and a high-priority process attempts to seize the lock and is blocked, the process holding the lock is temporarily given the higher priority of the blocked process. This hastens the time when the lock can be released, so that a low-priority process does not needlessly impede a higher-priority process.
In order to implement priority inheritance and retain high performance, the mutex lock is subject to the following restrictions:
- A mutex lock can be locked and unlocked only by an upper-half driver routine; that is, from code that has a process context. A mutex lock cannot be locked or unlocked in an interrupt routine.
- A mutex lock must be unlocked by the same process that locked it. It cannot be locked in one process identity and unlocked in another.
Because of these restrictions, a mutex lock can only be used to mediate between upper-half driver entry points. It is very effective for this purpose; you can use mutex locks to coordinate the use of global variables between upper-half entry points of a driver in a multiprocessor design.
When you need mutual exclusion between an upper-half entry point and the interrupt handler, use a basic lock. Resources that are shared with an interrupt handler should never be in use for more than a brief period. When your design requires a lock to be seized by one process and released in another, use a sleep lock or semaphore.
Using Sleep Locks
IRIX supports sleep lock functions that are compatible with SVR4. These functions are summarized in Table 9-18.
Functions for Sleep Locks
Function Name | Header Files | Can Sleep? | Purpose |
---|
SLEEP_ALLOC(D3) | types.h & kmem.h & ksynch.h | Y | Allocate and initialize a sleep lock. |
SLEEP_DEALLOC(D3) | types.h & ksynch.h | N | Deinitialize and deallocate a dynamically allocated sleep lock. |
SLEEP_INIT(D3) | types.h & ksynch.h | N | Initialize an existing sleep lock. |
SLEEP_DESTROY | types.h & ksynch.h | N | Deinitialize a sleep lock. |
SLEEP_LOCK(D3) | types.h & ksynch.h & param.h | Y | Acquire a sleep lock, waiting if necessary until the lock is free. |
SLEEP_LOCKAVAIL(D3) | types.h & ksynch.h | N | Query whether a sleep lock is available. |
SLEEP_LOCK_SIG(D3) | types.h & ksynch.h & param.h | Y | Acquire a sleep lock, waiting if necessary until the lock is free or a signal is received. |
SLEEP_TRYLOCK(D3) | types.h & ksynch.h | N | Try to acquire a sleep lock, returning a code if it is not free. |
SLEEP_UNLOCK(D3) | types.h & ksynch.h | N | Release a sleep lock. |
Although allocation and deallocation functions are supplied, a sleep_t type is a small object that is normally allocated as a static variable or as a field of a structure. The SLEEP_INIT() operation prepares a statically-allocated sleep_t for use. (In IRIX 6.2, a sleep_t is identical to a sema_t, but this situation could change in a future release.)
A sleep lock is similar to a mutex lock in that it is used for mutual exclusion between processes, and can be held across a function call that sleeps. A sleep lock does not have either the advantages or the restrictions of a mutex lock:
- A sleep lock can be seized by one process and released by another.
- A sleep lock can be set in an upper-half entry point and released in an interrupt routine.
- A sleep lock does not provide priority inheritance. When a low-priority process holds a sleep lock, a higher-priority process can be blocked, causing a priority inversion.
- A sleep lock does not support the instrumentation or the query functions supported for mutex locks.
Next | Prev | Up | Top | Contents | Index